﻿using mozhi.smarterp.Finance.Banks.Repository;
using mozhi.smarterp.Finance.Enums;
using mozhi.smarterp.Finance.Treasuries.Repositories;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Finance.Treasuries.Services
{
    public class PaymentManager : DomainService
    {
        private IPaymentRepository _repository;
        private IGuidGenerator _guidGenerator;
        private IOrganizationRepository _organizationRepository;
        private ISupplierRepository _supplierRepository;
        private ICustomerRepository _customerRepository;
        private IEmployeeRepository _employeeRepository;
        private IBankAccountRepository _bankAccountRepository;
        private INumberGeneratorRepository _numberGeneratorRepository;

        public PaymentManager(IPaymentRepository paymentRepository, IGuidGenerator guidGenerator,INumberGeneratorRepository numberGeneratorRepository,
            IOrganizationRepository organizationRepository, ISupplierRepository supplierRepository,IEmployeeRepository employeeRepository,ICustomerRepository customerRepository,IBankAccountRepository bankAccountRepository)
        {
            _repository = paymentRepository;
            _guidGenerator = guidGenerator;
            _organizationRepository = organizationRepository;
            _supplierRepository = supplierRepository;
            _customerRepository = customerRepository;
            _employeeRepository = employeeRepository;
            _bankAccountRepository = bankAccountRepository;
            _numberGeneratorRepository = numberGeneratorRepository;
        }

        public async Task<Payment> GetAsync(Guid? id , DateTime date, Guid? bankAccountId, Guid? supplierId, Guid? employeeId, Guid? customerId, TradingPartnerType tradingPartnerType,
            Guid currencyId, decimal exchangeRate, bool isAdvanced, bool isRefund , string comment , DocumentStatusType status)
        {
            var organization = await _organizationRepository.GetAsync();

            organization.ValidateFinanceDate(date);

            await Validate(bankAccountId, supplierId, employeeId , customerId);

            Payment payment;

            if(id.HasValue)
            {
                payment = await _repository.GetAsync(id.Value, false);

                payment.Change(date, bankAccountId, supplierId, employeeId, customerId, tradingPartnerType,
                    currencyId, exchangeRate, isAdvanced, isRefund);
            }
            else
            {
                var number = await GetNextNumberAsync();

                payment = new Payment(_guidGenerator.Create(), number, date, bankAccountId, supplierId, employeeId, customerId, tradingPartnerType,
                    currencyId, exchangeRate, isAdvanced, isRefund , comment , status);
            }

            return payment;
        }

        
        public async Task<PaymentItem> GetItemAsync(Guid? id , decimal amountFr , decimal? amount , string remark)
        {
            id = id ?? _guidGenerator.Create();

            var item = new PaymentItem(id.Value , null , null , amountFr , amount ,remark);

            return item;
        }

        /// <summary>
        /// 删除付款单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        public async Task DeleteAsync(Guid id)
        {
            var payment = await _repository.GetAsync(id);

            //有核销关系不允许删除

            //凭证如果审核不允许删除

            await _repository.DeleteAsync(payment);
        }

        #region
        private async Task Validate(Guid? bankAccountId, Guid? supplierId, Guid? employeeId , Guid? customerId)
        {
            if (supplierId.HasValue)
            {
                var supplier = await _supplierRepository.GetAsync(supplierId.Value);

                if (supplier == null)
                    throw new UserFriendlyException($"供应商：{supplierId.Value}不存在", "100000");

                supplier.Validate();
            }

            if (employeeId.HasValue)
            {
                var employee = await _employeeRepository.GetAsync(employeeId.Value);
                if (employee == null)
                    throw new UserFriendlyException($"员工：{employeeId.Value}不存在", "100000");

                employee.Validate();
            }

            if (customerId.HasValue)
            {
                var customer = await _customerRepository.GetAsync(customerId.Value);
                if (customer == null)
                    throw new UserFriendlyException($"客户：{customerId.Value}不存在", "100000");

                customer.Validate();
            }

            if (bankAccountId.HasValue)
            {
                var bankAccount = await _bankAccountRepository.FindAsync(bankAccountId.Value);

                if (bankAccount == null)
                    throw new UserFriendlyException($"银行账号：{bankAccountId}不存在", "100000");
            }
            
        }

        private async Task<string> GetNextNumberAsync()
        {
            var latestNumber = await _repository.GetLatestNumberAsync();

            var numberGenerator = await _numberGeneratorRepository.GetAsync((int)DocumentType.Payment, latestNumber ?? "");

            if (numberGenerator == null)
                throw new UserFriendlyException($"未设置类型为：{DocumentType.Payment}的编码规则", "100000");

            return numberGenerator?.Number;
        }

        #endregion
    }
}
